#include "common.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <malloc.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <semaphore.h>
#include <arpa/inet.h>
#include "vlan_proce.h"
#include "thread_recvcmd.h"

#include "info_apper.h"
#include "oper_device.h"

int udp_cmd_socket = 0;
struct sockaddr_in local_addr = {0};
struct sockaddr_in local_src = {0};
extern int thread_bmc_signal;
void thread_recvcmd()
{
	prctl(PR_SET_NAME, "thread_recvcmd");
	LOG_DEBUG("thread_recvcmd start !\n");

	int ret = 0;
	int len = sizeof(local_addr);
	unsigned char data[1024 * 64];
	unsigned int recvcount = 0;
	unsigned int recvcount_sum = 0;
	unsigned int yes = 1;
	struct ip_mreq mreq;
	pthread_t status_update_id;

	udp_cmd_socket = socket(AF_INET, SOCK_DGRAM, 0);

	if (udp_cmd_socket < 0)
	{
		LOG_DEBUG("udp_cmd_socket socket failed!\n");
		return;
	}
	//组播IP
	/* allow multiple sockets to use the same PORT number */
	if (setsockopt(udp_cmd_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
	{
		LOG_ERROR("Reusing ADDR failed");
		exit(1);
	}

	local_addr.sin_family = AF_INET;
	local_addr.sin_port = htons(GROUPCAST_PORT);
	local_addr.sin_addr.s_addr = htonl(INADDR_ANY);

	/** 构建目的地址参数, 发送数据时候用得到 */
	local_src.sin_family = AF_INET;
	local_src.sin_port = htons(GROUPCAST_PORT);
	local_src.sin_addr.s_addr = inet_addr(GROUPCAST_ADDR);

	ret = bind(udp_cmd_socket, (struct sockaddr *)&local_addr, sizeof(local_addr));
	if (ret < 0)
	{
		LOG_ERROR("udp_cmd_socket bind failed!\n");
		close(udp_cmd_socket);
		return;
	}
	//加入多播组
	mreq.imr_multiaddr.s_addr = inet_addr(GROUPCAST_ADDR);
	mreq.imr_interface.s_addr = inet_addr(LOCAL_ADDR);
	//      mreq.imr_interface.s_addr = htonl(INADDR_ANY);
	if (setsockopt(udp_cmd_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
	{
		LOG_ERROR("fail to setsockopt \n");
	}
	RecvCmd recv_cmd;
	RCTestMessage rctestMsg;
	OperDevice operd;
	
	VlanInfoEth vinfo = { 0 };
	int vindex = 0;
	for(; vindex < VALN_NUM; vindex++) {
		vinfo.vsd[vindex].speed = 0;
		vinfo.vsd[vindex].status = VSTATUS_AWAIT;
	}
	sendToMsg(&vinfo, INFO_VLAN);
	
	//启用新的线程, 用于状态BMC上报
	pthread_t sendToBMC300ms_id;
	pthread_create(&sendToBMC300ms_id, NULL, sendToBMC300ms, NULL);

	//开启状态信息上报线程
	// pthread_create(&status_update_id,NULL, status_update_pthread, NULL);
	//收采集指令
	int j = 0;
	pthread_t thread_bmcinfo_id;

	while (1)
	{
		//当前函数是阻塞式的
		memset(&recv_cmd, 0, sizeof(RecvCmd));
		memset(&rctestMsg, 0, sizeof(RecvCmd));
		recvcount = recvfrom(udp_cmd_socket, data, 1024, 0, (struct sockaddr *)&local_addr, &len);
		// LOG_DEBUG("recvcount is %d\n", recvcount);
		//Protocol parsing
#if  !SLAVER_MACHINE		
		if(data[2] == 0xAA) {
			//#note: BMC 上报
			MessageBMCInfo *bmcInfo = (MessageBMCInfo *)malloc(sizeof(MessageBMCInfo));	
			memcpy(bmcInfo, data, sizeof(MessageBMCInfo));
			if(!thread_bmc_signal) {
				thread_bmc_signal = 1;
				pthread_create(&thread_bmcinfo_id, NULL, sendToBmcManger, (void *)bmcInfo);
			}
			LOG_DEBUG("BMC 上报 \n");
			continue;
		}
#endif

		if(data[2] == 0x0B) {
			memcpy(&rctestMsg, data, sizeof(RCTestMessage));
			if(rctestMsg.tail == sizeof(RCTestMessage)) {
				recv_cmd.FileSize = 0x00;				//设置文件大小不限制
				recv_cmd.head = rctestMsg.head;
				recv_cmd.type = 0x05; 
				recv_cmd.luqu_status =rctestMsg.status;
				recv_cmd.tail =	sizeof(RecvCmd);
				pase_protocol(&recv_cmd);
			}else {
				LOG_ERROR("#ERR: error to verify 0x0B`s tail \n");
			}
		}
		//关机操作
		if (data[2] == 0x09) {
			memcpy(&operd, data, sizeof(OperDevice));
			oper_device(&operd);
		}

		if (data[2] == 0x05){
			// LOG_ERROR("#ERR: protocol iden is not 0x05, it is: %02x \n", data[2]);
			memcpy(&recv_cmd, data, sizeof(RecvCmd));
			pase_protocol(&recv_cmd);
		}

		if(data[2] == 0x0f) {
			printf("good \n");
		}
	}
}

/* 自检模式测试 */
void test_cmd(RecvCmd *recv_cmd) {
	recv_cmd->FileSize = 0x00;				//设置文件大小不限制
	recv_cmd->head = 0x00;
	recv_cmd->type = 0x05; 
	recv_cmd->luqu_status = 0x01;
	recv_cmd->tail = sizeof(RecvCmd);

#ifdef	VLAN_TEST
	recv_cmd->SourceData_gengzongmubiao = 1;
	recv_cmd->SourceData_kongzhixinxi = 1;
	// recv_cmd->SourceData_waibuyindao = 1;
	// recv_cmd->SourceData_mubiaoshibie = 1;
	// recv_cmd->SourceData_ganraozhencha_w = 1;
#endif

	del_cmd(recv_cmd);
}
/** 接收到命令后对命令解析 **/
#include "pcie_proce.h"
void del_cmd(RecvCmd *recv_cmd);
void pase_protocol(RecvCmd *recv_cmd) {
	if(recv_cmd->head == 0xC8C9) {		
		switch (recv_cmd->type)
		{
		case 0x01:
			/* BMC 报文 */
			break;
		
		case 0x02:
			/* 存储信息报文 */
			break;
		case 0x03:
			/* 光纤信息上报 */
			break;

		case 0x04:
			/* 网络信息上报 */
			break;

		case 0x05:
			/* 存储光纤报文 */
			if(recv_cmd->tail != sizeof(RecvCmd)) {
				LOG_ERROR("#ERR: recv_cmd.tail verify failed! \n");
				return;
			}
			del_cmd(recv_cmd);
			break;

		default:
			LOG_ERROR("#ERR: The protocol type is incorrect \n");
			break;
		}
	}
}
